using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;

namespace Common.Utilities.Security
{
    /// <summary>
    /// 
    /// </summary>
    public class LdapUtil
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static string GetRootDomain()
        {
            DirectoryEntry de = new DirectoryEntry();
            return de.Name.Substring(3);
        }

        #region users
        /// <summary>
        /// 
        /// </summary>
        /// <param name="matchPattern"></param>
        /// <returns></returns>
        public static List<string> GetUserFullNames(string matchPattern)
        {
            List<string> userFullNames = new List<string>();
            DirectorySearcher ds = new DirectorySearcher();
            ds.SearchRoot = new DirectoryEntry("");
            ds.Filter = LdapUtil.BuildLdapFilter(LdapObjectType.User, matchPattern);
            ds.PropertyNamesOnly = true;
            ds.PropertiesToLoad.Add("name");
            ds.Sort = new SortOption("name", SortDirection.Ascending);
            SearchResultCollection src = ds.FindAll();
            try
            {
                foreach (SearchResult sr in src)
                {
                    DirectoryEntry userDE = sr.GetDirectoryEntry();
                    userFullNames.Add(userDE.Name.Substring(3));
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                src.Dispose();
                ds.Dispose();
            }
            return userFullNames;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="matchPattern"></param>
        /// <returns></returns>
        public static List<string> GetUserNames(string matchPattern)
        {
            List<string> usernames = new List<string>();
            DirectorySearcher ds = new DirectorySearcher();
            ds.SearchRoot = new DirectoryEntry("");
            ds.Filter = LdapUtil.BuildLdapFilter(LdapObjectType.User, matchPattern);
            ds.PropertyNamesOnly = true;
            ds.PropertiesToLoad.Add("uid");
            ds.Sort = new SortOption("uid", SortDirection.Ascending);
            SearchResultCollection src = ds.FindAll();
            try
            {
                foreach (SearchResult sr in src)
                {
                    DirectoryEntry userDE = sr.GetDirectoryEntry();

                    //foreach (PropertyValueCollection propVals in userDE.Properties)
                    //{
                    //    Console.Write(propVals.Value.ToString());
                    //}
                    string uid = userDE.Properties["sAMAccountName"].Value.ToString();
                    usernames.Add(uid);
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                src.Dispose();
                ds.Dispose();
            }
            return usernames;
        }
        #endregion

        #region groups
        /// <summary>
        /// 
        /// </summary>
        /// <param name="matchPattern"></param>
        /// <returns></returns>
        public static List<string> GetGroups(string matchPattern)
        {
            List<string> groups = new List<string>();
            DirectorySearcher ds = new DirectorySearcher();
            ds.SearchRoot = new DirectoryEntry("");
            ds.Filter = LdapUtil.BuildLdapFilter(LdapObjectType.Group, matchPattern);
            ds.PropertyNamesOnly = true;
            ds.PropertiesToLoad.Add("name");
            ds.Sort = new SortOption("name", SortDirection.Ascending);
            SearchResultCollection src = ds.FindAll();
            try
            {
                foreach (SearchResult sr in src)
                {
                    DirectoryEntry userDE = sr.GetDirectoryEntry();
                    groups.Add(userDE.Name.Substring(3));
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                src.Dispose();
                ds.Dispose();
            }
            return groups;
        }
        #endregion

        #region filter
        private static string BuildLdapFilter(LdapObjectType objType, string filter)
        {
            string category = "user";
            switch (objType)
            {
                case LdapObjectType.User:
                    category = "user";
                    break;
                case LdapObjectType.Group:
                    category = "group";
                    break;
                case LdapObjectType.Computer:
                    category = "computer";
                    break;
                case LdapObjectType.Printer:
                    category = "printQueue";
                    break;
                default:
                    category = "user";
                    break;
            }
            return string.Format("(|(&(objectCategory={0})(name={1})))", category, filter);
        }
        #endregion
    }
}
